/******************************************************************************
 * Copyright (C) 2011 ShenZhen ComTop Information Technology Co.,Ltd
 * All Rights Reserved.
 * 本软件为深圳康拓普开发研制。未经本公司正式书面同意，其他任何个人、团体不得使用、
 * 复制、修改或发布本软件.
 *****************************************************************************/

package com.code.common.sessioncache.action;

import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;

import javax.servlet.http.HttpSession;

import com.code.common.cache.CacheFactory;
import com.code.common.cache.CacheInterface;
import com.code.common.sessioncache.model.Enumerator;
import com.code.common.utils.StringUtils;

/**
 * session包装类
 * 
 * @author 郑重
 * @since 1.0
 * @version 2010-8-25 郑重
 */
public final class HttpSessionSidWrapper extends HttpSessionWrapper {
    
    /** Map初始化容量大小 */
    private static final int MAP_SIZE = 100;
    
    /**
     * 新会话ID
     */
    private final String newSessionId;
    
    /**
     * 旧会话ID
     */
    private final String oldSessionId;
    
    /**
     * 缓存对象
     */
    private final CacheInterface cacheInterface;
    
    /** 无共享架构在Oracle Coherence缓存中的保存实例名称，如果是采用其他缓存组件服务，则该参数无效 */
    private static final String NSA_CACHE_NAME = "sessionShareCache";
    
    /**
     * @param newSessionId 新的session编号
     * @param oldSessionId 旧的session编号
     * @param session HttpSession
     */
    public HttpSessionSidWrapper(String newSessionId, String oldSessionId, HttpSession session) {
        super(session);
        
        cacheInterface = CacheFactory.getCache(NSA_CACHE_NAME);
        
        this.newSessionId = newSessionId;
        this.oldSessionId = oldSessionId;
        // 如果oldSessionId不为空表示会话过期清空缓存服务器属性
        if (StringUtils.isNotEmpty(oldSessionId)) {
            clearAttributesFromCache(getOldAttributeName());
        }
    }
    
    /**
     * 使之无效
     */
    @Override
    public void invalidate() {
        clearAttributesFromCache(getAttributeName());
        super.invalidate();
    }
    
    /**
     * 移除属性
     * 
     * @param key 键名
     */
    @Override
    public void removeAttribute(String key) {
        String strConvertKey = this.getConvertedName(key);
        // 移除cache缓存
        cacheInterface.removeAttribute(strConvertKey);
        // 移除会话缓存
        super.removeAttribute(key);
        // 移除会话键缓存
        removeAttributeName(key);
    }
    
    /**
     * 清空缓存服务器属性
     * 
     * @param attributeName 属性名称
     */
    public void clearAttributesFromCache(String attributeName) {
        try {
            Map<String, String> objAttributeMap = (Map<String, String>) cacheInterface.getAttribute(attributeName);
            if (objAttributeMap != null) {
                for (Iterator<String> objIter = objAttributeMap.keySet().iterator(); objIter.hasNext();) {
                    String strKey = objIter.next();
                    cacheInterface.removeAttribute(this.getConvertedName(strKey));
                }
                cacheInterface.removeAttribute(attributeName);
            }
        } catch (NoSuchElementException e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 得到属性
     * 
     * @param key 键名
     * @return Object
     */
    @Override
    public Object getAttribute(String key) {
        Object objResult = null;
        try {
            String strConvertKey = this.getConvertedName(key);
            objResult = super.getAttribute(key);
            // 如果结果为空则从缓存服务器中取出
            if (objResult == null) {
                objResult = cacheInterface.getAttribute(strConvertKey);
                super.setAttribute(key, objResult);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return objResult;
    }
    
    /**
     * 设置属性
     * 
     * @param key 键名
     * @param value 值
     */
    @Override
    public void setAttribute(String key, Object value) {
        try {
            String strConvertKey = this.getConvertedName(key);
            if (value != null) {
                cacheInterface.setAttribute(strConvertKey, value);
                setAttributeName(key);
                super.setAttribute(key, value);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 枚举所有属性
     * 
     * @return Enumeration<String>
     */
    @Override
    public Enumeration<String> getAttributeNames() {
        Enumeration<String> objEnumeration = super.getAttributeNames();
        try {
            if (objEnumeration == null) {
                objEnumeration =
                    new Enumerator(((Map<String, ?>) cacheInterface.getAttribute(getAttributeName())).keySet(), true);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return objEnumeration;
    }
    
    /**
     * 会话属性包装
     * 
     * @param name 名称
     * @return String 包装后名称
     */
    private String getConvertedName(String name) {
        return this.newSessionId + "_" + name;
    }
    
    /**
     * 属性集合名称
     * 
     * @return String
     */
    private String getAttributeName() {
        return this.newSessionId + "_ATTRIBUTE_NAMES";
    }
    
    /**
     * 属性集合名称
     * 
     * @return String
     */
    private String getOldAttributeName() {
        return this.oldSessionId + "_ATTRIBUTE_NAMES";
    }
    
    /**
     * 设置属性名到属性集合
     * 
     * @param key 键
     */
    private void setAttributeName(String key) {
        try {
            Map<String, String> objAttributeMap = (Map<String, String>) cacheInterface.getAttribute(getAttributeName());
            if (objAttributeMap == null) {
                objAttributeMap = new HashMap<String, String>(MAP_SIZE);
            }
            objAttributeMap.put(key, StringUtils.EMPTY);
            cacheInterface.setAttribute(getAttributeName(), objAttributeMap);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 删除属性集名从属性集合
     * 
     * @param key 键名
     */
    private void removeAttributeName(String key) {
        try {
            Map<String, String> objAttributeMap = (Map<String, String>) cacheInterface.getAttribute(getAttributeName());
            if (objAttributeMap != null) {
                objAttributeMap.remove(key);
                cacheInterface.setAttribute(getAttributeName(), objAttributeMap);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}